﻿// --- Copyright (c) 2006-2008 Stefan Kyntchev ---
// This software is written and copyrighted by Stefan Kyntchev 
// and BeyondPod Team members. All rights are reserved.
// Author contact: support@beyondpod.mobi
// ------------------------------------------------------------------------
// This file is part of BeyondPod RSS Feed Reader and Podcast manager
// (www.codeplex.com/BeyondPod) 
// BeyondPod is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// BeyondPod is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
//  
// You should have received a copy of the GNU General Public License
// along with BeyondPod. If not, see <http://www.gnu.org/licenses/>
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.Drawing;
using System.Windows.Forms;
using svs.Mobile.BeyondMedia.UiCore.GDI;

namespace svs.Mobile.BeyondMedia.Transitions
{
	internal class ViewTransitionSlide : ViewTransitionBasic
	{
		private readonly Timer _SequenceTimer = new Timer();
		private const double _transitionDuration = 1000;
		private double _transitionPct;
		private int _transitionStartTime;

		private Bitmap _ToBitmap;
		private Graphics _ToGraphics;

		private Bitmap _FromBitmap;
		private Graphics _fromGraphics;

		public ViewTransitionSlide()
		{
			_SequenceTimer.Interval = 11;
			_SequenceTimer.Tick += CalculateAnimationSequence;
		}

		public ViewTransitionManager.TransitionType SlideDirection { get; set; }

		public override void Execute()
		{
			if (ViewTransitionManager.FromView != ViewTransitionManager.ToView)
				OnTransitionStart();
			else
				OnTransitionEnd();
		}

		public override void  DrawScreenOn(Gdi mem, Rectangle rect)
		{
			var fromDC = _fromGraphics.GetHdc();
			var toDC = _ToGraphics.GetHdc();

			var toWidth = (int)(ViewTransitionManager.TransitionCanvas.Width * _transitionPct);

			if (SlideDirection == ViewTransitionManager.TransitionType.SlideLeft)
				toWidth = ViewTransitionManager.TransitionCanvas.Width - toWidth;

			int fromWidth = ViewTransitionManager.TransitionCanvas.Width - toWidth;

			if (SlideDirection == ViewTransitionManager.TransitionType.SlideLeft)
			{
				mem.BitBlt(0, 0, toWidth, _FromBitmap.Height,
				           fromDC, fromWidth, 0, Win32.ERop.SRCCOPY);

				mem.BitBlt(toWidth, 0, fromWidth, _ToBitmap.Height,
				           toDC, 0, 0, Win32.ERop.SRCCOPY);
			}
			else
			{
				mem.BitBlt(0, 0, toWidth, _FromBitmap.Height,
				           toDC, fromWidth, 0, Win32.ERop.SRCCOPY);

				mem.BitBlt(toWidth, 0, fromWidth, _ToBitmap.Height,
				           fromDC, 0, 0, Win32.ERop.SRCCOPY);
			}

			_fromGraphics.ReleaseHdc(fromDC);
			_ToGraphics.ReleaseHdc(toDC);
		}

		private void CalculateAnimationSequence(object sender, EventArgs e)
		{
			double scrollTime = (Environment.TickCount - _transitionStartTime);

			if (scrollTime < _transitionDuration)
			{
				double dur = scrollTime / _transitionDuration;

				dur -= 1.0;
				dur = Math.Pow(dur, 3);
				dur += 1.0;

				_transitionPct = dur;
				ViewTransitionManager.TransitionCanvas.RefreshControl();
			}
			else
			{
				_SequenceTimer.Enabled = false;
				OnTransitionEnd();
			}

		}

		protected override void OnTransitionStart()
		{
			base.OnTransitionStart();

			_FromBitmap = ViewTransitionManager.FromView.CreateScreenShot();
			_ToBitmap = ViewTransitionManager.ToView.CreateScreenShot();

			if (_FromBitmap == null || _ToBitmap == null)
			{
				base.OnTransitionStart();
				OnTransitionEnd();
				return;
			}

			_fromGraphics = Graphics.FromImage(_FromBitmap);
			_ToGraphics = Graphics.FromImage(_ToBitmap);

			_transitionPct = 0;

			ViewTransitionManager.TransitionCanvas.CurrentTransition = this;

			Application.DoEvents();

			_transitionStartTime = Environment.TickCount;
			_SequenceTimer.Enabled = true;
		}

		protected override void OnTransitionEnd()
		{
			ViewTransitionManager.TransitionCanvas.CurrentTransition = null;

			if (_fromGraphics != null)
			{
				_fromGraphics.Dispose();
				_fromGraphics = null;
			}

			if (_FromBitmap != null)
			{
				_FromBitmap.Dispose();
				_FromBitmap = null;
			}

			if (_ToGraphics != null)
			{
				_ToGraphics.Dispose();
				_ToGraphics = null;
			}

			if (_ToBitmap != null)
			{
				_ToBitmap.Dispose();
				_ToBitmap = null;
			}

			base.OnTransitionEnd();
		}

		public override bool IsTransitionAvailable()
		{
			return ViewTransitionManager.TransitionCanvas.AllocateOffscreenBitmap();
		}
	}
}